/********************************************************************************
* @file    bsp_tim.c
* @author  jianqiang.xue
* @version V1.1.0
* @date    2023-02-26
* @brief   本文件不再初始化GPIO，由APP_IO完成引脚初始化和复用。
********************************************************************************/
/* Public Includes ------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "RTE_Components.h"
#include CMSIS_device_header

#include "bsp_gpio.h"
#include "bsp_tim.h"

/* Private Includes ----------------------------------------------------------*/
#include "ls_gpio.h"
#include "ls_syscfg.h"

/* Private Define ------------------------------------------------------------*/
/* Private Typedef -----------------------------------------------------------*/
#if LS_TIM1_EN
TIM_HandleTypeDef *g_tim1_handle = NULL;
TIM_OC_InitTypeDef *g_tim1_oc_handle = NULL;
#endif
#if LS_TIM2_EN
TIM_HandleTypeDef *g_tim2_handle = NULL;
TIM_OC_InitTypeDef *g_tim2_oc_handle = NULL;
#endif

/* Public function prototypes -----------------------------------------------*/
#if LS_TIM1_EN
uint8_t bsp_tim1_pwm_init(bsp_tim_cfg_t *cfg) {
    if (g_tim1_handle) return 0; // 已经初始化过
    if (cfg == NULL) return 3; // 配置为空
    g_tim1_handle = malloc(sizeof(TIM_HandleTypeDef)); // 申请空间
    if (!g_tim1_handle) return 1; // TIM结构体无法申请空间
    g_tim1_oc_handle = malloc(sizeof(TIM_OC_InitTypeDef)); // 申请空间
    if (!g_tim1_oc_handle) {
        free(g_tim1_handle);
        return 2; // TIM类型结构体无法申请空间
    }
    // 结构体赋值
    g_tim1_handle->Instance               = TIM1;
    g_tim1_handle->Init.ClockDivision     = 0;                              // CKD 时钟分频因子(Clock division)
    g_tim1_handle->Init.RepetitionCounter = 0;                              // TIM1_RCR 重复计数器的值
    g_tim1_handle->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; // 禁止自动重装载

    g_tim1_handle->Init.Period            = cfg->period;      // 重装载值
    g_tim1_handle->Init.Prescaler         = cfg->prescaler;   // 预分频

    g_tim1_handle->Init.CounterMode  = TIM_COUNTERMODE_UP; // 边沿对齐模式 计数器向上计数
    if (cfg->level_logic)
        g_tim1_oc_handle->OCMode = TIM_OCMODE_PWM1; // PWM模式1 TIMx_CCMRx 高电平有效
    else
        g_tim1_oc_handle->OCMode = TIM_OCMODE_PWM2; // PWM模式2 TIMx_CCMRx 低电平有效
    __HAL_RCC_TIM1_CLK_ENABLE();
    /* Set TIMx instance */
    HAL_TIM_PWM_Init(g_tim1_handle);
    return 0;
}

void bsp_tim1_pwm_deinit(void) {
    if (!g_tim1_handle)
        return; // 未初始化
#if LS_PWM0_EN
    HAL_TIM_PWM_Stop(g_tim1_handle, TIM_CHANNEL_1);
#endif
#if LS_PWM1_EN
    HAL_TIM_PWM_Stop(g_tim1_handle, TIM_CHANNEL_2);
#endif
#if LS_PWM2_EN
    HAL_TIM_PWM_Stop(g_tim1_handle, TIM_CHANNEL_3);
#endif
#if LS_PWM3_EN
    HAL_TIM_PWM_Stop(g_tim1_handle, TIM_CHANNEL_4);
#endif
    HAL_TIM_PWM_DeInit(g_tim1_handle);
    __HAL_RCC_TIM1_CLK_DISABLE();
    free(g_tim1_handle);
    g_tim1_handle = NULL;
    if (g_tim1_oc_handle)
        free(g_tim1_oc_handle);
    g_tim1_oc_handle = NULL;
}

/**
 * @brief  将指定PWM通道使能，单纯的初始化并不会使能通道
 * @param  ch: TIM_CHANNEL_1 ~ TIM_CHANNEL_4
 * @param  en: 0--关闭  1--使能
 */
void bsp_tim1_pwm_ch_en(uint8_t ch, uint8_t en) {
    if (!g_tim1_handle || !g_tim1_oc_handle)
        return; // 未初始化
    switch (ch) {
        case TIM_CHANNEL_1:
            HAL_TIM_PWM_ConfigChannel(g_tim1_handle, g_tim1_oc_handle, TIM_CHANNEL_1);
            /* Enable the Capture compare channel */
            TIM_CCxChannelCmd(g_tim1_handle->Instance, TIM_CHANNEL_1, en);
            break;
        case TIM_CHANNEL_2:
            HAL_TIM_PWM_ConfigChannel(g_tim1_handle, g_tim1_oc_handle, TIM_CHANNEL_2);
            /* Enable the Capture compare channel */
            TIM_CCxChannelCmd(g_tim1_handle->Instance, TIM_CHANNEL_2, en);
            break;
        case TIM_CHANNEL_3:
            HAL_TIM_PWM_ConfigChannel(g_tim1_handle, g_tim1_oc_handle, TIM_CHANNEL_3);
            /* Enable the Capture compare channel */
            TIM_CCxChannelCmd(g_tim1_handle->Instance, TIM_CHANNEL_3, en);
            break;
        case TIM_CHANNEL_4:
            HAL_TIM_PWM_ConfigChannel(g_tim1_handle, g_tim1_oc_handle, TIM_CHANNEL_4);
            /* Enable the Capture compare channel */
            TIM_CCxChannelCmd(g_tim1_handle->Instance, TIM_CHANNEL_4, en);
            break;
        default:
            break;
    }
}
#endif

#if LS_TIM2_EN
uint8_t bsp_tim2_pwm_init(bsp_tim_cfg_t *cfg) {
    if (g_tim2_handle)
        return 0; // 已经初始化过
    if (cfg == NULL) return 3; // 配置为空
    g_tim2_handle = malloc(sizeof(TIM_HandleTypeDef)); // 申请空间
    if (!g_tim2_handle)
        return 1; // TIM结构体无法申请空间
    g_tim2_oc_handle = malloc(sizeof(TIM_OC_InitTypeDef)); // 申请空间
    if (!g_tim2_oc_handle) {
        free(g_tim2_handle);
        return 2; // TIM类型结构体无法申请空间
    }
    // 结构体赋值
    g_tim2_handle->Instance               = TIM2;
    g_tim2_handle->Init.ClockDivision     = 0;                              // CKD 时钟分频因子(Clock division)
    g_tim2_handle->Init.RepetitionCounter = 0;                              // TIM2_RCR 重复计数器的值
    g_tim2_handle->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; // 禁止自动重装载

    g_tim2_handle->Init.Period            = cfg->period;                 // 重装载值
    g_tim2_handle->Init.Prescaler         = cfg->prescaler;              // 预分频
    g_tim1_handle->Init.CounterMode       = TIM_COUNTERMODE_UP; // 边沿对齐模式 计数器向上计数
    if (cfg->level_logic)
        g_tim2_oc_handle->OCMode = TIM_OCMODE_PWM1; // PWM模式1 TIMx_CCMRx 高电平有效
    else
        g_tim2_oc_handle->OCMode = TIM_OCMODE_PWM2; // PWM模式2 TIMx_CCMRx 低电平有效
    
    __HAL_RCC_TIM2_CLK_ENABLE();
    /* Set TIMx instance */
    HAL_TIM_PWM_Init(g_tim2_handle);
    return 0;
}

void bsp_tim2_pwm_deinit(void) {
    if (!g_tim2_handle)
        return; // 未初始化
#if LS_PWM4_EN
    HAL_TIM_PWM_Stop(g_tim2_handle, TIM_CHANNEL_1);
#endif
#if LS_PWM5_EN
    HAL_TIM_PWM_Stop(g_tim2_handle, TIM_CHANNEL_2);
#endif
#if LS_PWM6_EN
    HAL_TIM_PWM_Stop(g_tim2_handle, TIM_CHANNEL_3);
#endif
#if LS_PWM7_EN
    HAL_TIM_PWM_Stop(g_tim2_handle, TIM_CHANNEL_4);
#endif
    HAL_TIM_PWM_DeInit(g_tim2_handle);
    __HAL_RCC_TIM2_CLK_DISABLE();
    free(g_tim2_handle);
    g_tim2_handle = NULL;
    if (g_tim2_oc_handle)
        free(g_tim2_oc_handle);
    g_tim2_oc_handle = NULL;
}

/**
 * @brief  将指定PWM通道使能，单纯的初始化并不会使能通道
 * @param  ch: TIM_CHANNEL_1 ~ TIM_CHANNEL_4
 * @param  en: 0--关闭  1--使能
 */
void bsp_tim2_pwm_ch_en(uint8_t ch, uint8_t en) {
    if (!g_tim2_handle || !g_tim2_oc_handle)
        return; // 未初始化
    switch (ch) {
        case TIM_CHANNEL_1:
            HAL_TIM_PWM_ConfigChannel(g_tim2_handle, (TIM_OC_InitTypeDef *)g_tim2_oc_handle, TIM_CHANNEL_1);
            /* Enable the Capture compare channel */
            TIM_CCxChannelCmd(g_tim2_handle->Instance, TIM_CHANNEL_1, en);
            break;
        case TIM_CHANNEL_2:
            HAL_TIM_PWM_ConfigChannel(g_tim2_handle, (TIM_OC_InitTypeDef *)g_tim2_oc_handle, TIM_CHANNEL_2);
            /* Enable the Capture compare channel */
            TIM_CCxChannelCmd(g_tim2_handle->Instance, TIM_CHANNEL_2, en);
            break;
        case TIM_CHANNEL_3:
            HAL_TIM_PWM_ConfigChannel(g_tim2_handle, (TIM_OC_InitTypeDef *)g_tim2_oc_handle, TIM_CHANNEL_3);
            /* Enable the Capture compare channel */
            TIM_CCxChannelCmd(g_tim2_handle->Instance, TIM_CHANNEL_3, en);
            break;
        case TIM_CHANNEL_4:
            HAL_TIM_PWM_ConfigChannel(g_tim2_handle, (TIM_OC_InitTypeDef *)g_tim2_oc_handle, TIM_CHANNEL_4);
            /* Enable the Capture compare channel */
            TIM_CCxChannelCmd(g_tim2_handle->Instance, TIM_CHANNEL_4, en);
            break;
        default:
            break;
    }
}
#endif
